home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
MPW_TOOL
/
TOOLS
/
TOOLS_WI
/
BYACC__
/
SYMTAB.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-11-19
|
5KB
|
312 lines
#include <assert.h>
#include <stdio.h>
#include "defs.h"
#include "new.h"
#include "symtab.h"
#include "tokens.h"
#define TABLE_SIZE 1009
bucket **symtab;
bucket *first_symbol;
bucket *last_symbol;
int
compare(f, s, m, g, t, n)
int f, g;
register char *s, *t;
int m, n;
{
register int i;
register int c1, c2;
register int result;
result = 0;
for (i = ( m < n ? m : n ); i > 0 && result == 0; i--)
if ((c1 = *s++) != (c2 = *t++)) result = c1 - c2;
if (result == 0)
{
result = m - n;
if (result == 0) result = f - g;
}
return (result);
}
int
hash(str, len)
char *str;
int len;
{
register char *s;
register int i, n;
assert(str && len > 0);
s = str;
n = *s;
i = len;
while (--i > 0)
{
n = 31*n + *s++;
while (n >= TABLE_SIZE) n -= TABLE_SIZE;
}
return (n);
}
char *
mk_prname(form, key, length)
int form;
register char *key;
int length;
{
register int i, k;
register int c;
register int close_quote;
register char *name;
if (form == IDENTIFIER)
k = 1;
else
k = 3;
for (i = 0; i < length; i++)
{
c = key[i];
switch (c)
{
case NEWLINE:
case CR:
case QUOTE:
case DOUBLE_QUOTE:
case BACKSLASH:
case HT:
case VT:
case BS:
case FF:
k += 2;
default:
if (PRINTABLE(c))
k++;
else
k += 4;
}
}
name = NEW2(k, char);
switch (form)
{
case IDENTIFIER:
k = 0;
close_quote = NUL;
break;
case CHARACTER:
name[0] = QUOTE;
k = 1;
close_quote = QUOTE;
break;
case STRING:
name[0] = DOUBLE_QUOTE;
k = 1;
close_quote = DOUBLE_QUOTE;
break;
case TYPE_IDENTIFIER:
name[0] = '<';
k = 1;
close_quote = '>';
break;
default:
panic("mk_prname");
}
for (i = 0; i < length; i++)
{
c = key[i];
switch (c)
{
case NEWLINE:
name[k] = BACKSLASH;
name[k+1] = 'n';
k += 2;
break;
case CR:
name[k] = BACKSLASH;
name[k+1] = 'r';
k += 2;
break;
case QUOTE:
case DOUBLE_QUOTE:
case BACKSLASH:
name[k] = BACKSLASH;
name[k+1] = c;
k += 2;
break;
case HT:
name[k] = BACKSLASH;
name[k+1] = 't';
k += 2;
break;
case VT:
name[k] = BACKSLASH;
name[k+1] = 'v';
k += 2;
break;
case BS:
name[k] = BACKSLASH;
name[k+1] = 'b';
k += 2;
break;
case FF:
name[k] = BACKSLASH;
name[k+1] = 'f';
k += 2;
break;
default:
if (PRINTABLE(c))
{
name[k] = c;
k++;
}
else
{
name[k] = BACKSLASH;
name[k+1] = ((c >> 6) & 3) + '0';
name[k+2] = ((c >> 3) & 7) + '0';
name[k+3] = (c & 7) + '0';
k += 4;
}
}
}
name[k] = close_quote;
return (name);
}
bucket *
make_bucket(form, key, length)
int form;
char *key;
int length;
{
register int i;
register char *s, *t;
register bucket *bp;
bp = NEW(bucket);
bp->length = length;
bp->key = s = NEW2(length + 1, char);
bp->prname = mk_prname(form, key, length);
bp->value = UNDEFINED;
t = key;
for (i = length; i > 0; i--)
*s++ = *t++;
bp->form = form;
if (form == CHARACTER || form == STRING)
bp->class = TERMINAL;
last_symbol->next = bp;
last_symbol = bp;
return (bp);
}
tabinit()
{
register int i;
register bucket *bp;
symtab = NEW2(TABLE_SIZE, bucket *);
for (i = 0; i < TABLE_SIZE; i++)
symtab[i] = NIL(bucket);
bp = NEW(bucket);
bp->length = 5;
bp->key = mk_prname(IDENTIFIER, "error", 5);
bp->prname = mk_prname(IDENTIFIER, "error", 5);
bp->value = UNDEFINED;
bp->index = 1;
bp->form = IDENTIFIER;
bp->class = TERMINAL;
bp->used = 1;
first_symbol = bp;
last_symbol = bp;
symtab[hash(bp->key, 5)] = bp;
}
bucket *
lookup(form, key, length)
int form;
char *key;
int length;
{
register int cc, hash_value;
register bucket *bp, *tbp;
hash_value = hash(key, length);
bp = symtab[hash_value];
if (bp == NIL(bucket))
symtab[hash_value] = bp = make_bucket(form, key, length);
else
{
for (;;)
{
if (cc = compare(form, key, length, bp->form, bp->key, bp->length))
{
tbp = bp;
if (cc < 0)
{
bp = bp->left;
if (bp == NIL(bucket))
{
tbp->left = bp = make_bucket(form, key, length);
break;
}
}
else
{
bp = bp->right;
if (bp == NIL(bucket))
{
tbp->right = bp = make_bucket(form, key, length);
break;
}
}
}
else
break;
}
}
return (bp);
}
free_symtab()
{
register bucket *bp, *tbp;
bp = first_symbol;
while (bp)
{
tbp = bp->next;
FREE(bp->key);
FREE(bp);
bp = tbp;
}
FREE(symtab);
}